# 2.30选股，2:50购入；
# 第二天10点出；不持有超过2天；盈利2个点就出；尾盘没有盈利直接割；开盘低开谨慎，甚至直接割;破不了5日线，直接出；
# 目标 80w 分 10只；

# 只买阴线，回调到10日线；10日线距离20日线较近，(如果距离很远说明已经大涨过没有后续)；
# 有量能，回调到10日线，有涨停版的优先买入

# main.py
# 选股逻辑：
# 1、收盘小于开盘
# 2、20日线小于五日线、十日线
# 3、30日线小于五日线、十日线
# 4、价格在10日均线的0.95-1.05之间
# 5、价格大于20日线、30日线的 0.75

# 6、排除换手率低于5%或者高于10%的
# 7、排除流通市值大于200亿
# 8、价格3-30元
# 9、去除ST
# 10、去除创业板

import akshare as ak
import pandas as pd
import time
from datetime import datetime
import os

# from send_mail import send_email  # 引入邮件模块

# 禁用代理（避免 ProxyError）
os.environ["http_proxy"] = ""
os.environ["https_proxy"] = ""

# ================== 参数 ==================
TURNOVER_MIN = 5                # 换手率下限 (%)
TURNOVER_MAX = 10               # 换手率上限 (%)
MCAP_MAX = 200e8                # 流通市值上限（200亿）
PRICE_MIN = 3                   # 价格下限
PRICE_MAX = 30                  # 价格上限
DEVIATION_RATIO10 = 0.05        # 十日线偏差比 (±5%)
DEVIATION_MUL30 = 0.75          # 30/20日线偏差倍率

# ================== 第一步：获取实时全市场快照，外部过滤 ==================
print("获取全市场快照数据...")
spot_all = ak.stock_zh_a_spot_em()

spot_filtered = spot_all[
    (spot_all["换手率"].astype(float).between(TURNOVER_MIN, TURNOVER_MAX)) &
    (spot_all["流通市值"].astype(float) * 1e8 <= MCAP_MAX) &
    (spot_all["最新价"].astype(float).between(PRICE_MIN, PRICE_MAX)) &
    (~spot_all["名称"].str.startswith("ST")) &
    (~spot_all["代码"].str.startswith(("300", "301")))  # 去除创业板（300/301开头）
]

codes = spot_filtered["代码"].tolist()
print(f"初筛后剩余 {len(codes)} 只股票，进入日线计算...")

# 转换为字典映射，加快取值速度
spot_map = spot_filtered.set_index("代码").to_dict(orient="index")

results = []

# ================== 第二步：循环股票，计算均线条件 ==================
for code in codes:
    try:
        daily = ak.stock_zh_a_daily(symbol=code, adjust="qfq")
        if len(daily) < 30:
            continue

        # 计算均线
        for window in [5, 10, 20, 30]:
            daily[f"ma{window}"] = daily["close"].rolling(window).mean()

        latest = daily.iloc[-1]

        spot = spot_map.get(code)
        if not spot:
            continue

        turnover = float(spot["换手率"])       # %
        mcap = float(spot["流通市值"]) * 1e8  # 亿转元
        name = spot["名称"]

        # ============ 均线相关条件 ============
        cond1 = latest["close"] < latest["open"]
        cond2 = (latest["ma20"] < latest["ma5"]) and (latest["ma20"] < latest["ma10"])
        cond3 = (latest["ma30"] < latest["ma5"]) and (latest["ma30"] < latest["ma10"])
        cond4 = (latest["ma10"] * (1 - DEVIATION_RATIO10) <= latest["close"] <= latest["ma10"] * (1 + DEVIATION_RATIO10))
        cond5 = (latest["close"] > latest["ma20"] * DEVIATION_MUL30) and (latest["close"] > latest["ma30"] * DEVIATION_MUL30)

        if all([cond1, cond2, cond3, cond4, cond5]):
            results.append({
                "code": code,
                "name": name,
                "close": latest["close"],
                "turnover_rate": turnover,
                "mcap(元)": mcap,
            })

        time.sleep(0.1)  # 控制请求频率

    except Exception as e:
        print(f"处理 {code} 出错: {e}")
        continue

# ================== 保存结果 ==================
today_str = datetime.today().strftime("%Y_%m_%d")
file_name = f"/app/output/result_{today_str}.csv"

df_result = pd.DataFrame(results)
df_result.to_csv(file_name, index=False, encoding="utf-8-sig")

print(f"筛选完成，共 {len(df_result)} 只股票，结果已保存 {file_name}")

# ================== 发送邮件 ==================
# send_email(file_name)
